import { nextTick, reactive, watch } from 'vue'

// 让 dom 可以拖拽
import domDrag from './controller/domDrag'
// 设置排序
import setOrder from './controller/set-order'

import type {
  IGridMeta,
  // IGridItem,
  IGridItemList,
  IGridSelection
} from '../types/50-grid'

import type {
  IDragInfo,
  IDragEvent
} from '../types/70-drag'

/**
 * 数据列表的拖拽相关的操作，记录调整后的td 的宽度，调整td的顺序，移除td
 * @param gridMeta 用于排序 colOrder 
 * @param itemMeta 获取列的信息
 * @param table table 的 dom
 * @param deleteDom 移除 dom 的确认对话框
 * @param modCol ctrl + 单击 th 的事件
 * @returns 
 */
export default function gridDrag(
  gridMeta: IGridMeta,
  itemMeta: IGridItemList,
  table: HTMLTableElement,
  deleteDom: (col: any, cb: () => void) => void,
  modCol: (colId: string | number, dragInfo: IDragInfo, event: any) => void
) {
  
  /**
   * 移除选择的字段
   * @param { IDragInfo } dragInfo 拖拽信息
   */
  const _setRemove = (dragInfo: IDragInfo) => {
    const col = itemMeta[dragInfo.sourceId]
    // 调用外部的确认对话框
    deleteDom(col, () => {
      // 确认移除，才会执行回调
      gridMeta.colOrder.splice(dragInfo.sourceIndex, 1)
    }) 
  }

  /**
   * 设置th的对齐方式
   */
  const _setThAlgin = (dragInfo: IDragInfo) => {
    // 判断 th 还是 td
    const alignKind = (dragInfo.ctrl) ? 'header-align' : 'align'
    // 获取列的 meta 
    const col = itemMeta[dragInfo.sourceId]
    // 判断当前对齐方式：左、中、右
    switch (col[alignKind]) {
      case 'left': // -> 变成居中
        col[alignKind] = (dragInfo.isLeft) ? 'left' : 'center'
        break
      case 'center': // -> 变成右对齐； <- 变成左对齐
        col[alignKind] = (dragInfo.isLeft) ? 'left' : 'right'
        break
      case 'right': // <- 变成居中
        col[alignKind] = (dragInfo.isLeft) ? 'center' : 'right'
        break
    }
  }

  // 调整 th 的宽度后，记录新的宽度
  const _setThWidth = (e) => {
    // 等待刷新
    setTimeout(() => {
      // 监听事件，获取调整后的 th 的宽度
      // 遍历 table 的第一行（标题）的 th
      const arr = Array.from(table.rows[0].cells)
      let i = -1
      arr.forEach(element => {
        if (i === -1) { // 跳过第一列（check）
          i = 0
        } else {
          itemMeta[gridMeta.colOrder[i++]].width = element.offsetWidth
        }
      })
    }, 1000)
  }
  
  // 拖拽信息
  const dragInfo = reactive<IDragInfo>({
    timeout: null, // 设置拖拽出去的 setTimeout
    oldDom: {style:{border:'', borderStyle: ''}}, // 记录之前的拖拽 dom
    state: '', // 拖拽状态，拖拽中（pending），拖拽结束（end）
    offsetX: 0,
    isLeft: true, // 是否在 th 的左侧结束拖拽，左侧或者右侧。
    ctrl: false, // 是否按下了ctrl
    sourceId: '', // 开始拖拽的th对应的字段ID
    targetLabel: '', // 开始的 th 的 label
    target: undefined, // 开始 的 dom
    targetId: '', // 结束拖拽的th对应的字段ID
    sourceIndex: 0, // 开始拖拽的位置
    targetIndex: 0 // 结束拖拽的位置
  })
  
  // 整合拖拽事件
  const _dragEvent = {
    setAlign() {
      _setThAlgin(dragInfo)
    },
    setOrder() {
      setOrder(gridMeta.colOrder, dragInfo) // 调整顺序、交换位置
    },
    removeDom() {
      _setRemove(dragInfo) // 移除
    },
    modCol(colId, event) {
      if (typeof modCol === 'function')
        modCol(colId, dragInfo, event) // 单击控件（字段）触发的事件
    }
  }

  /**
   * 列表的初始化设置
   */
  const girdSetup = () => {
    // 调整 th 的宽度后，记录新的宽度
    table.removeEventListener("mouseup", _setThWidth)
    table.addEventListener("mouseup", _setThWidth)

    // 找到 可以拖拽的 dom，这里是 table 的 tr[0] 的 th 集合
    // const className = 'el-table__header'
    // const table = el.getElementsByClassName(className)[0]
    const tr = table.rows[0] // 表头
    const tdCount = tr.cells.length // 列数

    // 遍历表头，设置 th 的拖拽，如果第一列是复选框，那么不算
    const start = tdCount - gridMeta.colOrder.length
    for (let i = start; i < tdCount; i++) {
      const th = tr.cells[i]
      const colId = gridMeta.colOrder[i - start]
      // 给 th 设置拖拽事件 domEvents, 
      const thDrag = new domDrag(th, gridMeta.colOrder, dragInfo, colId, _dragEvent)
    }
  }

  // 监听 字段变化，重新设置拖拽。
  watch(gridMeta, () => {
    nextTick(() => {
      setTimeout(() => {
        girdSetup() // 重新绘制
      }, 500)
    })
  })

  return {
    girdSetup // 列表设置拖拽
  }

}